#include <timerManager.h>
#include <cnotify.h>
#include <framework.h>
#include <commands.h>
#include <utils.h>
#include <keyMap.h>

STATUS TimerManager::dump(TextTable& t)
{
    t.setTableName("TimerManager");
    t.addHeader("timerName");
    t.addHeader("IntervalMs");
    t.addHeader("status").endOfRow();

    std::lock_guard<std::mutex> lock{ this->m_mutex };
    for (auto& iter : m_timers)
    {
        t.add(iter.second->getName());
        t.add(utils::format("%d", iter.second->getInterval()));
        t.add(status_to_string(iter.second->isRunning())).endOfRow();
    }

    return OK;
}

STATUS TimerManager::preInit()
{
    return OK;
}
STATUS TimerManager::postInit()
{
    return registerMessageListener(MODULE_TIMER_MGR);
}
STATUS TimerManager::destory()
{
    stoped.store(true);
    stopAllTimers();
    clearAllTimers();
    return OK;
}
PROCESS_IMPL_DESC(TimerManager, process)
{
    PROCESS_BEGIN()
    PROCESS_CALL(CMD_SYS_SHUTDOWN, sysShutdown)
    PROCESS_END(RET_ERROR)
}

PROCESS_IMPL_DESC(TimerManager, sysShutdown)
{
    return destory();
}

STATUS TimerManager::addTimer(const std::string& id, unsigned int intervalSec, Callback callback)
{
    COND_CHECK_RET_ERROR(stoped.load());

    COND_CHECK_RET_ERROR(hasTimer(id));

    std::lock_guard<std::mutex> lock(m_mutex);
    m_timers[id] = std::make_unique<Timer>(id.c_str(), intervalSec * 1000, std::move(callback));
    m_timers[id]->start();

    return OK;
}

STATUS TimerManager::removeTimer(const std::string& id)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    m_timers.erase(id);
    return OK;
}

STATUS TimerManager::startTimer(const std::string& id)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    auto it = m_timers.find(id);
    if (it != m_timers.end()) 
    {
        it->second->start();
        return OK;
    }

    return RET_ERROR;
}

STATUS TimerManager::stopTimer(const std::string& id)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    auto it = m_timers.find(id);
    if (it != m_timers.end()) 
    {
        it->second->stop();
        return OK;
    }
    return RET_ERROR;
}

STATUS TimerManager::resetTimer(const std::string& id)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    auto it = m_timers.find(id);
    if (it != m_timers.end()) 
    {
        it->second->reset();
        return OK;
    }
    return RET_ERROR;
}

bool TimerManager::hasTimer(const std::string& id) 
{
    std::lock_guard<std::mutex> lock(m_mutex);
    return m_timers.find(id) != m_timers.end();
}

bool TimerManager::isTimerRunning(const std::string& id)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    auto it = m_timers.find(id);
    return it != m_timers.end() && it->second->isRunning();
}

void TimerManager::startAllTimers() 
{
    std::lock_guard<std::mutex> lock(m_mutex);
    for (auto& [id, timer] : m_timers) 
    {
        timer->start();
    }
}

void TimerManager::stopAllTimers() 
{
    std::lock_guard<std::mutex> lock(m_mutex);
    for (auto& [id, timer] : m_timers) 
    {
        timer->stop();
    }
}

void TimerManager::clearAllTimers() 
{
    std::lock_guard<std::mutex> lock(m_mutex);
    m_timers.clear();
}

REG_TO_FRAMEWORK(TimerManager, MODULE_TIMER_MGR)